package com.smcaiot.filesync.starter.util;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author: cz
 * @Date: 2023/6/30
 * @Description:
 */
@Slf4j
public class ReflectTool {

    public static <T> Field getFieldByAnnotation(Class<T> clz, Class annotation) {
        Field[] fields = clz.getDeclaredFields();
        Assert.notEmpty(fields, "无法找到文件地址");
        Optional<Field> first = Arrays.stream(fields)
                .filter(f -> f.isAnnotationPresent(annotation)).findFirst();
        Assert.isTrue(first.isPresent(),
                String.format("缺少%s注解，无法找到文件地址", annotation.getSimpleName()));
        return first.get();
    }

    public static <T> void setFieldValue(T entity, Class annotation, String smallPath) {
        Field field = getFieldByAnnotation(entity.getClass(), annotation);
        ReflectUtil.setFieldValue(entity, field, smallPath);
    }

    public static <T> String getFieldValue(T entity, Class annotation) {
        Field field = getFieldByAnnotation(entity.getClass(), annotation);
        Object fieldValue = ReflectUtil.getFieldValue(entity, field);
        return Objects.isNull(fieldValue) ? null : (String) fieldValue;
    }

    public static <T> String getFieldName(T entity, Class annotation) {
        Field field = getFieldByAnnotation(entity.getClass(), annotation);
        return field.getName();
    }

    public static Class getClass(String className) {
        try {
            return ClassUtils.forName(className, null);
        } catch (Exception e) {
            log.warn("找不定指定类：{}", className);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取类的泛型参数
     *
     * @param clz 类的class
     * @return 泛型的class
     */
    public static Class getGenericParameterClass(Class clz) {
        try {
            Type type = ((ParameterizedType) clz.getGenericSuperclass()).getActualTypeArguments()[0];
            return Class.forName(type.getTypeName());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
